package operations;

import java.util.ArrayList;
import java.util.LinkedList;

import parsing.*;
import Functions.*;


public class FunctionOperations implements FunctionOperationsInterface
{

	LinkedList<Element> myFunction ;
	LinkedList<Element> myFunctionDiff = new LinkedList<Element>();
	
	public FunctionOperations(String function)
	{
		 Parser p = new ParserImplementation(function);
	     myFunction =p.parse();
	}
	
	public FunctionOperations(LinkedList<Element> e)
	{
		myFunction  = e;
	}

	
	
	@Override
	public LinkedList<Element> differentiate() 
	{
		for(int i=0;i<myFunction.size();i++)
		{
			diffRule(myFunction.get(i));
		}
		return myFunctionDiff;
	}
	
	@Override
	public double evaluate(double num) 
	{
		double value =0;
		for(int i=0;i<myFunction.size();i++)
		{
			double termValue=1;
			Element f = myFunction.get(i);
			ArrayList<Functions> term = f.getTerm();
			for(int j=0;j<term.size();j++)
			{
				if(term.get(j)!=null)
				{
					termValue *= term.get(j).evaluate(num);
				}
			}
			value += termValue;
		}
		return value;
	}
	
	private void diffRule(Element e)
	{
		ArrayList<Functions> elements = e.getTerm();
		for(int i=0;i<elements.size();i++)
		{
			ArrayList<Functions> terms = new ArrayList<Functions>();
			if(elements.get(i)!=null)
			{
				Element f = elements.get(i).differentiate();
				if(f!=null)
				{
					for(int j=0;j<f.getTerm().size();j++)
					{
						terms.add(f.getTerm().get(j));
					}
					for(int j=0;j<elements.size();j++)
					{
						if(i!=j)
						{
							terms.add(elements.get(j));
						}
					}
					Element newEle = new Element(terms);
					myFunctionDiff.add(newEle);
				}
			}
		}
	}
	
	public static void main(String[] args) {
		//String x = "5*x-x*sin(x)+ exp(5x)- exp(5x) + sin(x) - 5*sin(x) + x*sin^2(5x^2 +7)";
		//String x ="x*sin(x)"; 
		String x = "exp(-x)";
		FunctionOperations f = new FunctionOperations(x);
		//f.differentiate();
		double k1 = f.evaluate(1);
		double d1 = Math.exp(-1);
		System.out.println(k1);
		System.out.println(d1);
//		System.out.println("---------------------------");
//		double k2 = f.evaluate(1);
//		double d2 = 1+3-Math.cos(4);
//		System.out.println(k2);
//		System.out.println(d2);
//		System.out.println("---------------------------");
//		double k = f.evaluate(100);
//		double d = 10000+300-Math.cos(103);
//		System.out.println(k);
//		System.out.println(d);
//		System.out.println("---------------------------");
//		double k3 = f.evaluate(200);
//		double d3 = 40000+600-Math.cos(203);
//		System.out.println(k3);
//		System.out.println(d3);
//		System.out.println("---------------------------");
	}
	

}
